/*
******************************************************************************************************* 
**  Copyright (C) 2019, 苏州检易生物科技有限公司 
**  All rights reserved. 
** 
**  FileName:       	tube.c
**  Description:	
**  Author:        	 
**  Version				v0.1
**  Date:           	2019-09-06
**	Function List： 
**  History:         
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	调试开关
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/
#include "tube.h"
#include "log_console.h"
#include "crc16.h"
#include "data_backup.h"
#include "tcp_transfer.h"
#include "os_config.h"
#include "timer.h"
/*
*********************************************************************************************************
*                                              	宏定义
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                              	结构体定义
*********************************************************************************************************
*/

 
/*
*********************************************************************************************************
*                                              	函数原型声明
*********************************************************************************************************
*/


/*
*********************************************************************************************************
*                                              	全局变量定义
*********************************************************************************************************
*/
tube_list_t m_tube_list;
/*
*********************************************************************************************************
*                                              	模块静态变量定义
*********************************************************************************************************
*/

static uint8_t rt_tube_mp_buff[RT_MEMPOOL_BYTE_SIZE(TI_POOL_SIZE,sizeof(tube_t))];


/*
*********************************************************************************************************
*                                               本地函数声明
*********************************************************************************************************
*/
//static void data_backup_callback(protocol_cmd_t cmd,uint8_t* buff,uint16_t size);
/*
*********************************************************************************************************
*					
*********************************************************************************************************
*/
tube_err_t 	tube_init(void)
{
	memset(&m_tube_list,0,sizeof(m_tube_list));
	
	m_tube_list.max_size=TI_POOL_SIZE;
	/* 创建内存池 */
	if(RT_EOK != rt_mp_init(&m_tube_list.rt_mem,
		"tube msg pool",
		rt_tube_mp_buff,
		sizeof(rt_tube_mp_buff),
		sizeof(tube_t)
		))
	{
		Critical_Log("tube mem create failed!\r\n");
	}
	return TUBE_ERR_NONE;
}
tube_t* tube_malloc(uint32_t period)
{
	tube_t* p_tube = rt_mp_alloc(&m_tube_list.rt_mem,RT_WAITING_FOREVER);
	if(p_tube == NULL)
	{
		Critical_Log("tube mem get failed!\n");
		return NULL;
	}
	rt_base_t it = rt_hw_interrupt_disable();
	
	m_tube_list.cur_size++;
	if(m_tube_list.head==NULL)
	{
		m_tube_list.head=p_tube;
	}
	else
	{
		tube_t *tail_tube=m_tube_list.head;
		while(tail_tube->tube_next!=NULL)
			{tail_tube=tail_tube->tube_next;}
		tail_tube->tube_next=p_tube;
	}
	memset(p_tube, 0, sizeof(tube_t));	
	p_tube->tube_status  = TUBE_ACCEPT;
	
	/* 设置反应盘位置 */
	p_tube->period=period;
#if PRODUCT_NAME_IVD_900
	if(p_tube->period%(REACTION_GRID_NUM*4) < REACTION_GRID_NUM)
		p_tube->rnd_pos=REACTION_OUTSIDE;
	else if(p_tube->period%(REACTION_GRID_NUM*4) < 2*REACTION_GRID_NUM)
		p_tube->rnd_pos=REACTION_SECOND;
	else if(p_tube->period%(REACTION_GRID_NUM*4) < 3*REACTION_GRID_NUM)
		p_tube->rnd_pos=REACTION_THIRD;
	else
		p_tube->rnd_pos=REACTION_INSIDE;
#else
	if(p_tube->period%(REACTION_GRID_NUM*2) < REACTION_GRID_NUM)
		p_tube->rnd_pos=REACTION_OUTSIDE;
	else
		p_tube->rnd_pos=REACTION_INSIDE;
#endif
	rt_hw_interrupt_enable(it);
	return p_tube;
}
tube_err_t tube_free(tube_t* p_tube)
{
	rt_base_t it = rt_hw_interrupt_disable();
	if(p_tube)
	{
		tube_t* dst_tube=m_tube_list.head;
		if(dst_tube==p_tube)
		{
			m_tube_list.head=p_tube->tube_next;
			m_tube_list.cur_size--;
		}
		else{
			while(dst_tube->tube_next!=NULL)
			{
				if(dst_tube->tube_next==p_tube)
				{
					m_tube_list.cur_size--;
					dst_tube->tube_next=p_tube->tube_next;
					break;
				}
				dst_tube=dst_tube->tube_next;
			}
		}
//		memset(p_tube,0,sizeof(tube_t));
		Trace_Log("Test tube free,left %d;\r\n",m_tube_list.cur_size);
		rt_mp_free(p_tube);
	}
	rt_hw_interrupt_enable(it);
	return TUBE_ERR_NONE;	
}
tube_t* tube_get(uint32_t cur_period,uint32_t test_period) 
{
	rt_base_t it = rt_hw_interrupt_disable();
	tube_t * p_tube=m_tube_list.head;
	while(p_tube!=NULL)
	{
		if((cur_period-p_tube->period)==test_period)
			break;
		p_tube=p_tube->tube_next;
	}
	rt_hw_interrupt_enable(it);
	return p_tube;
}
tube_err_t tube_add_sample(tube_t * p_tube,sample_info_t* p_sample)
{
	rt_base_t it = rt_hw_interrupt_disable();
	if(p_tube!=NULL && p_sample != NULL)
	{
		memcpy(&p_tube->sample_id,p_sample->sample_id,SAMPLE_ID_LEN);
		p_tube->test_type = p_sample->test_type;
		if(p_sample->dilute > 1)
		{
			p_tube->method = p_sample->method | METHOD_DILUTE_MSK;
		}
		else
			p_tube->method = p_sample->method;
		p_tube->dilute_sample_ul = DILLUTE_SAMPLE_UL(p_sample->dilute);
		p_tube->dilute_ul = (p_sample->dilute - 1) * p_tube->dilute_sample_ul;
		p_tube->alkali = p_sample->alkali;
		p_tube->sample_ul = p_sample->sample_ul;
		tube_status_change(p_tube,TUBE_REACTION,TUBE_ERR_NONE);
	}
	rt_hw_interrupt_enable(it);
	return TUBE_ERR_NONE;
}
tube_err_t tube_add_tube(tube_t * p_tube,tube_t * p_dilute)
{
	rt_base_t it = rt_hw_interrupt_disable();
	if(p_tube!=NULL && p_dilute != NULL)
	{
		memcpy(&p_tube->sample_id,p_dilute->sample_id,SAMPLE_ID_LEN);
		p_tube->test_type = p_dilute->test_type;
		p_tube->method = p_dilute->method & (~METHOD_DILUTE_MSK);
		p_tube->dilute_ul = 0;
		p_tube->alkali = p_dilute->alkali;
		p_tube->sample_ul = p_dilute->sample_ul;
		tube_add_reagent(p_tube,p_dilute->p_reagent);
//		tube_status_change(p_dilute,TUBE_FAILED,TUBE_ERR_DILUTE);
	}
	rt_hw_interrupt_enable(it);
	return TUBE_ERR_NONE;
}
tube_err_t tube_add_dilute(tube_t * p_tube,reagent_info_t* p_dilute)
{
	rt_base_t it = rt_hw_interrupt_disable();
	if(p_tube!=NULL && p_dilute != NULL)
	{
		p_tube->p_dilute = p_dilute;
	}
	rt_hw_interrupt_enable(it);
	return TUBE_ERR_NONE;
}
tube_err_t tube_add_reagent(tube_t * p_tube,reagent_info_t* p_reagent)
{
	rt_base_t it = rt_hw_interrupt_disable();
	if(p_tube!=NULL && p_reagent != NULL)
	{
		p_tube->p_reagent=p_reagent;
		memcpy(p_tube->reagent_id,p_reagent->name,REAGENT_ID_LEN);
		memcpy(p_tube->reagent_batch,p_reagent->batch,REAGENT_BATCH_LEN);
		memcpy(p_tube->reagent_bottle,p_reagent->bottle,REAGENT_BOTTLE_LEN);
//		p_tube->status = TUBE_REAGENT;
	}
	rt_hw_interrupt_enable(it);
	return TUBE_ERR_NONE;
}
tube_err_t tube_failed(tube_t * p_tube,tube_err_t err_code)
{
//	rt_base_t it = rt_hw_interrupt_disable();
//	if(p_tube != NULL && p_tube->tube_err == TUBE_ERR_NONE)
//	{
//		tube_status_change(p_tube,TUBE_FAILED,err_code);
////		p_tube->status=TUBE_FAILED;
////		p_tube->tube_err=err_code;
//		Critical_Log("Tube failed ,error code %d!\r\n",err_code);
////		tube_upld(p_tube);
//	}
////	tube_status_upload(p_tube,UPLOAD_TUBE_ERROR);
//	rt_hw_interrupt_enable(it);
//	return TUBE_ERR_NONE;
}
/*两步法的反应杯重新进入反应盘后需要更新内外圈位置信息*/
tube_err_t tube_reload(uint32_t cur_period,tube_t* p_tube)
{
	if(p_tube == NULL || p_tube->method != METHOD_TWO_STEP)
		return TUBE_ERR_NONE;
	rt_base_t it = rt_hw_interrupt_disable();
	if(cur_period%(REACTION_GRID_NUM*2) < REACTION_GRID_NUM)
		p_tube->rnd_pos=REACTION_OUTSIDE;
	else
		p_tube->rnd_pos=REACTION_INSIDE;
	rt_hw_interrupt_enable(it);
	return TUBE_ERR_NONE;
}
tube_t* tube_between(uint32_t cur_period,uint8_t start,uint8_t end)
{
	rt_base_t it = rt_hw_interrupt_disable();
	tube_t* p_tube=m_tube_list.head;
	while(p_tube!=NULL)
	{
		if(((cur_period-p_tube->period)>=start)&&((cur_period-p_tube->period)<=end))
			break;
		else 
			p_tube=p_tube->tube_next;
	}
	rt_hw_interrupt_enable(it);
	return p_tube;
}
//uint32_t tube_get_ul(tube_t * p_tube,test_process_t process)
//{
//	ASSERT(p_tube);
//	switch(process)
//	{
//		case TEST_PROCESS_R1:
//			if(p_tube->method == (METHOD_NORMAL | METHOD_FAST))		
//			break;
//		case TEST_PROCESS_R2:
//			break;
//		case TEST_PROCESS_R2_DL:
//			break;
//		case TEST_PROCESS_MAGNET:
//			break;
//		case TEST_PROCESS_SAMPLE:
//			break;
//		default:return 0;
//	}
//	return 0;
//}
tube_err_t tube_upld(tube_t* p_tube)
{
	if(p_tube == NULL)
		return TUBE_ERR_NONE;
	uint16_t size = sizeof(tube_backup_t) - sizeof(uint16_t);
	if(p_tube->tube_err == TUBE_ERR_NONE && p_tube->tube_status == TUBE_SUCCESS)
		tcp_transfer_push(UPLD_PHOTON,(uint8_t*)&(p_tube->test_type),size);
	
	if(p_tube->test_type != TEST_TYPE_NORMAL)
		return TUBE_ERR_NONE;
	
	tube_backup_t m_backup;
	memcpy((uint8_t*)&(m_backup.test_type),(uint8_t*)&(p_tube->test_type),size);
	m_backup.backup_checksum = ModBusCRC((uint8_t*)&(m_backup.test_type),size);
	
	uint16_t index = m_backup.sample_id[0] + (m_backup.sample_id[1]<<8);
	
	photon_backup_write((uint8_t*)&(m_backup),index,sizeof(tube_backup_t));
	
	return TUBE_ERR_NONE;
}
void tube_status_change(tube_t *p_tube,tube_status_t status,tube_err_t err)
{
	tube_status_upld_t m_upload;
	if(p_tube == NULL || p_tube->tube_err != TUBE_ERR_NONE)
		return;
	rt_base_t it = rt_hw_interrupt_disable();
	if(err != TUBE_ERR_NONE)
	{
		p_tube->tube_status = TUBE_FAILED;
		p_tube->tube_err = err;
	}
	else if(p_tube->tube_status == status)
	{
		rt_hw_interrupt_enable(it);
		return;
	}
	else
	{
		p_tube->tube_status = status;
		p_tube->tube_err = err;
	}
//	if(err == TUBE_ERR_DILUTE)
//	{
//		rt_hw_interrupt_enable(it);
//		return;
//	}
	m_upload.test_type = p_tube->test_type;
	m_upload.tube_status = p_tube->tube_status;
	m_upload.tube_err = p_tube->tube_err;
	memcpy(m_upload.sample_id,p_tube->sample_id,SAMPLE_ID_LEN);
	rt_hw_interrupt_enable(it);
	if(p_tube->tube_status == TUBE_TESTING || p_tube->tube_status == TUBE_REACTION || p_tube->tube_status == TUBE_FAILED)
	{
		tcp_transfer_push(UPLD_TEST_STATUS,(uint8_t*)&m_upload,sizeof(m_upload));
	}
	/*稀释杯不上传测试结果& 不保存*/
	if(( (p_tube->method & METHOD_DILUTE_MSK) == 0) &&
		(p_tube->tube_status == TUBE_SUCCESS || p_tube->tube_status == TUBE_FAILED))
	{
		tube_upld(p_tube);
	}
	return;
}
tube_t* tube_get_by_sid(uint8_t* sample_id)
{
	ASSERT(sample_id);
	rt_base_t it = rt_hw_interrupt_disable();
	tube_t * p_tube=m_tube_list.head;
	while(p_tube!=NULL)
	{
		if(memcmp(p_tube->sample_id,sample_id,SAMPLE_ID_LEN) == 0)
			break;
		p_tube=p_tube->tube_next;
	}
	rt_hw_interrupt_enable(it);
	return p_tube;
}
void sample_failed(sample_node_t* p_sample,tube_err_t err)
{
	if(p_sample == NULL)
		return;
	tube_t tube;
	memset(&tube,0,sizeof(tube_t));
	tube.test_type = p_sample->m_sample_info.test_type;
	memcpy(tube.sample_id,p_sample->m_sample_info.sample_id,SAMPLE_ID_LEN);
//	tube.tube_status = TUBE_FAILED;
//	tube.tube_err = err;
//	tube_upld(&tube);
	tube_status_change(&tube,TUBE_FAILED,err);
}
/*往反应杯中添加液体,计算反应杯液量,同时返回 (当前反应杯液量-固定偏移量)*/
//uint32_t tube_ul(tube_t* p_tube,int32_t add_ul)
//{
//	if(p_tube == NULL)
//		return 0;
//	p_tube->volume += add_ul;
//	if(p_tube->volume < TUBE_BSAE_VOLUME)
//		return 0;
//	return p_tube->volume - TUBE_BSAE_VOLUME;
//}